package com.csun.cmny.provider.service.impl;

import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.DmcWatchDataStepMapper;
import com.csun.cmny.provider.model.domain.DmcWatchDataStep;
import com.csun.cmny.provider.model.dto.watch.WatchStepQueryDto;
import com.csun.cmny.provider.model.vo.watch.*;
import com.csun.cmny.provider.service.DmcWatchDataService;
import com.csun.cmny.provider.service.DmcWatchDataStepService;
import com.csun.cmny.provider.utils.TimeUtils;
import com.csun.cmny.util.PublicUtil;
import io.swagger.models.auth.In;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2019-01-24 15:18
 * @Description: the class dmc watch data step service impl
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class DmcWatchDataStepServiceImpl extends BaseService<DmcWatchDataStep>
        implements DmcWatchDataStepService {

    @Resource
    private DmcWatchDataService dmcWatchDataService;

    @Resource
    private DmcWatchDataStepMapper dmcWatchDataStepMapper;

    /**
     * query hist watch step with day
     *
     * @param watchStepQueryDto watch step day query dto
     * @return watch step day vo
     */
    @Override
    public WatchStepDayVo queryHistStepWithDay(WatchStepQueryDto watchStepQueryDto) {

        // 是否有数据
        boolean flag = false;

        dmcWatchDataService.getWatchDataByDeviceId(watchStepQueryDto.getDeviceId());

        // 4.查询手环数据
        List<WatchStepHourVo> watchStepHourVos = dmcWatchDataStepMapper
                .queryHistStepWithDay(watchStepQueryDto);

        WatchStepDayVo watchStepDayVo = new WatchStepDayVo();

        if (PublicUtil.isNotEmpty(watchStepHourVos)) {
            flag = true;
        }

        Map<Integer, WatchStepHourVo> map = null;
        if (flag) {
            map = watchStepHourVos
                    .stream().collect(Collectors.toMap(WatchStepHourVo::getHour, a -> a, (k1, k2)->k1));
        }

        Integer hour = 0;
        boolean tag = true;
        WatchStepHourVo last = new WatchStepHourVo();

        /**
         * @date    2020-04-09
         * @author  chisj
         * @desc    修复bug #4675
         */
        Integer totalStep = 0;
        Float totalCalorie = 0f;
        Float totalKilometer = 0f;

        for (; hour < 24; ) {
            tag = true;
            watchStepDayVo.getHourVoList()[hour] = new WatchStepHourVo();
            watchStepDayVo.getHourVoList()[hour].setHour(hour);
            if (flag) {
                WatchStepHourVo data = map.get(hour);
                if (PublicUtil.isEmpty(data)) {
                    tag = false;
                    data = new WatchStepHourVo();
                }

                if (hour.equals(0)) {
                    BeanUtils.copyProperties(data, watchStepDayVo.getHourVoList()[hour]);
                } else {
                    if (tag) {
                        watchStepDayVo.getHourVoList()[hour].setStep(data.getStep() - last.getStep());
                        watchStepDayVo.getHourVoList()[hour].setCalorie(data.getCalorie() - last.getCalorie());
                        watchStepDayVo.getHourVoList()[hour].setKilometer(data.getKilometer() - last.getKilometer());
                    }
                }
                if (tag) {
                    last = data;
                }
            }
            totalStep += watchStepDayVo.getHourVoList()[hour].getStep();
            totalCalorie += watchStepDayVo.getHourVoList()[hour].getCalorie();
            totalKilometer += watchStepDayVo.getHourVoList()[hour].getKilometer();

            hour++;
        }

        watchStepDayVo.setStepTotal(totalStep);
        watchStepDayVo.setCalorieTotal(totalCalorie);
        watchStepDayVo.setKilometerTotal(totalKilometer);

        return watchStepDayVo;
    }

    /**
     * query hist watch step week vo
     *
     * @param watchStepQueryDto watch step query dto
     * @return the watch step week vo
     */
    @Override
    public WatchStepWeekVo queryHistStepWithWeek(WatchStepQueryDto watchStepQueryDto) {

        // 是否有数据
        boolean flag = false;

        dmcWatchDataService.getWatchDataByDeviceId(watchStepQueryDto.getDeviceId());

        // 4.查询手环数据
        List<WatchStepDay> watchStepDays = dmcWatchDataStepMapper
                .queryHistStepWithWeek(watchStepQueryDto);

        WatchStepWeekVo watchStepWeekVo = new WatchStepWeekVo();

        if (PublicUtil.isNotEmpty(watchStepDays)) {
            flag = true;
        }

        Map<Integer, WatchStepDay> map = null;
        if (flag) {
            map = watchStepDays
                    .stream().collect(Collectors.toMap(WatchStepDay::getDay, a -> a, (k1, k2)->k1));
        }

        Integer day = 0;
        mapToWatchStepDay(map, day, watchStepWeekVo.getDayVoList(), flag);

        watchStepWeekVo.setStepTotal(watchStepDays.stream().mapToInt(WatchStepDay::getStep).sum());
        watchStepWeekVo.setCalorieTotal((float) watchStepDays.stream()
                .mapToDouble(WatchStepDay::getCalorie).sum());
        watchStepWeekVo.setKilometerTotal((float) watchStepDays.stream()
                .mapToDouble(WatchStepDay::getKilometer).sum());

        return watchStepWeekVo;
    }

    /**
     * query hist step with month vo
     *
     * @param watchStepQueryDto watch step query dto
     * @return the watch step month vo
     */
    @Override
    public WatchStepMonthVo queryHistStepWithMonth(WatchStepQueryDto watchStepQueryDto) {

        // 是否有数据
        boolean flag = false;

        dmcWatchDataService.getWatchDataByDeviceId(watchStepQueryDto.getDeviceId());

        // 4.查询手环数据
        List<WatchStepDay> watchStepDays = dmcWatchDataStepMapper
                .queryHistStepWithMonth(watchStepQueryDto);

        WatchStepMonthVo watchStepMonthVo = new WatchStepMonthVo();

        // 根据日期获取天数
        int days = 0;
        try {
            days = TimeUtils.getDaysOfMonth(watchStepQueryDto.getDate());
        } catch (Exception e) {
            e.printStackTrace();
        }

        watchStepMonthVo.setDayVoList(new WatchStepDay[days]);

        if (PublicUtil.isNotEmpty(watchStepDays)) {
            flag = true;
        }

        Map<Integer, WatchStepDay> map = null;
        if (flag) {
            map = watchStepDays
                    .stream().collect(Collectors.toMap(WatchStepDay::getDay, a -> a, (k1, k2)->k1));
        }

        Integer day = 0;
        mapToWatchStepDay(map, day, watchStepMonthVo.getDayVoList(), flag);

        watchStepMonthVo.setStepTotal(watchStepDays.stream().mapToInt(WatchStepDay::getStep).sum());
        watchStepMonthVo.setCalorieTotal((float) watchStepDays.stream()
                .mapToDouble(WatchStepDay::getCalorie).sum());
        watchStepMonthVo.setKilometerTotal((float) watchStepDays.stream()
                .mapToDouble(WatchStepDay::getKilometer).sum());

        return watchStepMonthVo;
    }

    /**
     * 删除步数
     *
     * @param deviceId the device id
     * @return the int
     */
    @Override
    public Integer removeDmcWatchDataStep(Long deviceId) {

        DmcWatchDataStep dmcWatchDataStep = new DmcWatchDataStep();
        dmcWatchDataStep.setDeviceId(deviceId);

        return dmcWatchDataStepMapper.delete(dmcWatchDataStep);
    }

    private void mapToWatchStepDay(Map<Integer, WatchStepDay> map, Integer day, WatchStepDay[] dayVoList, boolean flag) {
        for (; day < dayVoList.length; ) {
            dayVoList[day] = new WatchStepDay();
            dayVoList[day].setDay(day + 1);
            if (flag) {
                WatchStepDay data = map.get(day + 1);
                if (PublicUtil.isNotEmpty(data)) {
                    BeanUtils.copyProperties(data, dayVoList[day]);
                }
            }
            day++;
        }
    }
}
